jetcrab\lexer\scanners/
number.rs

1use crate::lexer::{LexerError, TokenKind};
2
3pub trait NumberReader {
4    fn read_number(&mut self) -> Result<TokenKind, LexerError>;
5}
6
7impl<T> NumberReader for T
8where
9    T: LexerCore,
10{
11    fn read_number(&mut self) -> Result<TokenKind, LexerError> {
12        let mut number = String::new();
13        let mut is_hex = false;
14        let mut is_binary = false;
15        let mut is_octal = false;
16
17        if self.source()[self.pos()] == '0' && self.pos() + 1 < self.source().len() {
18            match self.source()[self.pos() + 1] {
19                'x' | 'X' => {
20                    is_hex = true;
21                    number.push('0');
22                    number.push(self.source()[self.pos() + 1]);
23                    self.advance_pos();
24                    self.advance_pos();
25                }
26                'b' | 'B' => {
27                    is_binary = true;
28                    number.push('0');
29                    number.push(self.source()[self.pos() + 1]);
30                    self.advance_pos();
31                    self.advance_pos();
32                }
33                'o' | 'O' => {
34                    is_octal = true;
35                    number.push('0');
36                    number.push(self.source()[self.pos() + 1]);
37                    self.advance_pos();
38                    self.advance_pos();
39                }
40                _ => {}
41            }
42        }
43
44        while self.pos() < self.source().len() {
45            let c = self.source()[self.pos()];
46
47            if is_hex {
48                if c.is_ascii_hexdigit() {
49                    number.push(c);
50                    self.advance_pos();
51                } else {
52                    break;
53                }
54            } else if is_binary {
55                if c == '0' || c == '1' {
56                    number.push(c);
57                    self.advance_pos();
58                } else {
59                    break;
60                }
61            } else if is_octal {
62                if ('0'..='7').contains(&c) {
63                    number.push(c);
64                    self.advance_pos();
65                } else {
66                    break;
67                }
68            } else if c.is_ascii_digit() || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-'
69            {
70                number.push(c);
71                self.advance_pos();
72            } else {
73                break;
74            }
75        }
76
77        if self.pos() < self.source().len() && self.source()[self.pos()] == 'n' {
78            number.push('n');
79            self.advance_pos();
80            return Ok(TokenKind::BigInt(number));
81        }
82
83        if is_hex {
84            match u64::from_str_radix(&number[2..], 16) {
85                Ok(n) => Ok(TokenKind::Number(n as f64)),
86                Err(_) => Err(LexerError::InvalidNumber(number)),
87            }
88        } else if is_binary {
89            match u64::from_str_radix(&number[2..], 2) {
90                Ok(n) => Ok(TokenKind::Number(n as f64)),
91                Err(_) => Err(LexerError::InvalidNumber(number)),
92            }
93        } else if is_octal {
94            match u64::from_str_radix(&number[2..], 8) {
95                Ok(n) => Ok(TokenKind::Number(n as f64)),
96                Err(_) => Err(LexerError::InvalidNumber(number)),
97            }
98        } else {
99            match number.parse::<f64>() {
100                Ok(n) => Ok(TokenKind::Number(n)),
101                Err(_) => Err(LexerError::InvalidNumber(number)),
102            }
103        }
104    }
105}
106
107use crate::lexer::scanners::LexerCore;